package com.example.travelservlet.entertainment.service;

import com.example.travelservlet.city.service.CityService;
import com.example.travelservlet.entertainment.dao.EntertainmentMapper;
import com.example.travelservlet.entertainment.repository.EntertainmentRepository;
import com.example.travelservlet.entity.City;
import com.example.travelservlet.entity.Entertainment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * @author hxy
 * @date 2022/11/8 12:00
 */
@Service
public class EntertainmentServiceImpl implements EntertainmentService{
    @Autowired
    private EntertainmentRepository entertainmentRepository;

    @Autowired
    private CityService cityService;
    @Autowired
    private EntertainmentMapper entertainmentMapper;




    @Override
    public Page findEntertainmentsByCityIdAndEntertainmentIds(City city, List<String> entertainmentIds, Pageable pageable,String type) {
        Specification specification = new Specification<Entertainment>() {
            @Override
            public Predicate toPredicate(Root<Entertainment> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                List<Predicate> predicates = new ArrayList<>();
                List<Predicate> predicateList = new ArrayList<>();
                predicates.add(criteriaBuilder.equal(root.get("cityId"),city.getCityId()));
                predicates.add(criteriaBuilder.equal(root.get("type"),type));
                Predicate predicate2 = criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
                if (entertainmentIds.size()!=0){
                    for (String entertainmentId : entertainmentIds){
                        predicateList.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("entertainmentId"),entertainmentId)));
                    }
                }
                Predicate predicate = criteriaBuilder.or(predicateList.toArray(new Predicate[predicateList.size()]));
                return criteriaQuery.where(predicate2).getRestriction();
            }
        };
        return entertainmentRepository.findAll(specification,pageable);
    }

    @Override
    public List<Entertainment> findEntertainmentsByCityIdAndEntertainmentIds(City city, List<String> entertainmentIds, String type) {
        Specification specification = new Specification<Entertainment>() {
            @Override
            public Predicate toPredicate(Root<Entertainment> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                List<Predicate> predicateList = new ArrayList<>();
                predicates.add(criteriaBuilder.equal(root.get("cityId"),city.getCityId()));
                predicates.add(criteriaBuilder.equal(root.get("type"),type));
                Predicate predicate2 = criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
                if (entertainmentIds.size()!=0){
                    for (String entertainmentId : entertainmentIds){
                        predicateList.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("entertainmentId"),entertainmentId)));
                    }
                }
                Predicate predicate = criteriaBuilder.or(predicateList.toArray(new Predicate[predicateList.size()]));

                return criteriaQuery.where(predicate2,predicate).getRestriction();
            }
        };
        return entertainmentRepository.findAll(specification);
    }

    @Override
    public Page findEntertainmentsByEntertainmentIds(List<String> entertainmentIds, Pageable pageable) {
        Specification specification = new Specification<Entertainment>() {
            @Override
            public Predicate toPredicate(Root<Entertainment> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if (entertainmentIds.size()!=0){
                    for (String entertainmentId : entertainmentIds){
                        predicates.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("entertainmentId"),entertainmentId)));
                    }
                }
                return criteriaBuilder.or(predicates.toArray(new Predicate[predicates.size()]));
            }
        };

        return entertainmentRepository.findAll(specification,pageable);
    }

    @Override
    public Page findAll(City city, Pageable pageable,String type) {
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(criteriaBuilder.equal(root.get("cityId"),city.getCityId()));
                predicates.add(criteriaBuilder.equal(root.get("type"),type));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        return entertainmentRepository.findAll(specification,pageable);
    }

    @Override
    public List<Entertainment> findAll(City city, String type) {
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(criteriaBuilder.equal(root.get("cityId"),city.getCityId()));
                predicates.add(criteriaBuilder.equal(root.get("type"),type));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        return entertainmentRepository.findAll(specification);
    }

    @Override
    public Page findResearch(String cityId, Pageable pageable, String str) {
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(criteriaBuilder.equal(root.get("cityId"),cityId));
                predicates.add(criteriaBuilder.like(root.get("name"),"%"+ str +"%"));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        return entertainmentRepository.findAll(specification,pageable);
    }

    @Override
    public Entertainment findEntertainmentByEntertainmentId(String entertainmentId) {
        return entertainmentRepository.findEntertainmentByEntertainmentId(entertainmentId);
    }

    @Override
    public List<Entertainment> findEntertainmentsByCityIdAndType(String cityId,String type) {
        return entertainmentRepository.findEntertainmentsByCityIdAndType(cityId,type);
    }

    @Override
    public Entertainment saveEntertainment(Entertainment entertainment) {
        return entertainmentRepository.save(entertainment);
    }

    @Override
    public void deleteEntertainment(Entertainment entertainment) {
        entertainmentRepository.delete(entertainment);
    }

    @Override
    public List<Entertainment> findSceneries() {
        List<Entertainment> entertainments =entertainmentRepository.findEntertainmentsByType("scenery");
//        List<Entertainment> entertainmentList = new ArrayList<>();
//        for (Entertainment entertainment:entertainments){
//            entertainment.setCityId(cityService.findCityById(entertainment.getCityId()).getCityName());
//            entertainmentList.add(entertainment);
//        }
        return entertainments;
    }

    @Override
    public List<Entertainment> findSceneries1(int page, int size) {
        int pageIndex = (page-1)*size;
        List<Entertainment> entertainments = entertainmentMapper.findSceneries1(pageIndex, size);
        List<Entertainment> entertainmentList = new ArrayList<>();
        for (Entertainment entertainment:entertainments){
            entertainment.setCityId(cityService.findCityById(entertainment.getCityId()).getCityName());
            entertainmentList.add(entertainment);
        }

        return entertainmentList;
    }


//    @Override
//    public Page findSceneries1(Pageable pageable) {
//        Specification specification = new Specification() {
//            @Override
//            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
//                List<Predicate> predicates = new ArrayList<>();
//                predicates.add(criteriaBuilder.equal(root.get("type"),"scenery"));
//                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
//            }
//        };
//        return entertainmentRepository.findAll(specification,pageable);
//    }

    @Override
    public List<Entertainment> findFoods() {
        List<Entertainment> entertainments =entertainmentRepository.findEntertainmentsByType("food");
//        List<Entertainment> entertainmentList = new ArrayList<>();
//        for (Entertainment entertainment:entertainments){
//            entertainment.setCityId(cityService.findCityById(entertainment.getCityId()).getCityName());
//            entertainmentList.add(entertainment);
//        }
        return entertainments;
    }

    @Override
    public List<Entertainment> findFoods1(int page, int size) {
        int pageIndex = (page-1)*size;
        List<Entertainment> entertainments = entertainmentMapper.findFoods1(pageIndex, size);
        List<Entertainment> entertainmentList = new ArrayList<>();
        for (Entertainment entertainment:entertainments){
            entertainment.setCityId(cityService.findCityById(entertainment.getCityId()).getCityName());
            entertainmentList.add(entertainment);
        }

        return entertainmentList;
    }

//    @Override
//    public Page findFoods1(Pageable pageable) {
//        Specification specification = new Specification() {
//            @Override
//            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
//                List<Predicate> predicates = new ArrayList<>();
//                predicates.add(criteriaBuilder.equal(root.get("type"),"food"));
//                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
//            }
//        };
//        return entertainmentRepository.findAll(specification,pageable);
//    }
    @Override
    public List<Entertainment> findSceneriesByKeyWord(String key, Integer page, Integer size) {
        int pageIndex = (page-1)*size;
        List<Entertainment> entertainments = entertainmentMapper.findSceneriesByKeyWord(key,pageIndex,size);
        List<Entertainment> entertainmentList = new ArrayList<>();
        for (Entertainment entertainment:entertainments){
            entertainment.setCityId(cityService.findCityById(entertainment.getCityId()).getCityName());
            entertainmentList.add(entertainment);
        }

        return entertainmentList;

//        Specification specification = new Specification() {
//            @Override
//            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
//                List<Predicate> predicates = new ArrayList<>();
//                predicates.add(criteriaBuilder.equal(root.get("type"),"scenery"));
//                predicates.add(criteriaBuilder.like(root.get("name"),"%"+ key +"%"));
//                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
//            }
//        };
////        List<Entertainment> entertainments =entertainmentRepository.findAll(specification);
////        List<Entertainment> entertainmentList = new ArrayList<>();
////        for (Entertainment entertainment:entertainments){
////            entertainment.setCityId(cityService.findCityById(entertainment.getCityId()).getCityName());
////            entertainmentList.add(entertainment);
////        }
//        return entertainmentRepository.findAll(specification,pageable);
    }

    @Override
    public List<Entertainment> findAlls() {
        return entertainmentRepository.findAll();
    }

    @Override
    public List<Entertainment> findSceneriesByKeyWord(String key) {
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(criteriaBuilder.equal(root.get("type"),"scenery"));
                predicates.add(criteriaBuilder.like(root.get("name"),"%"+ key +"%"));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        List<Entertainment> entertainments =entertainmentRepository.findAll(specification);
        List<Entertainment> entertainmentList = new ArrayList<>();
        for (Entertainment entertainment:entertainments){
            entertainment.setCityId(cityService.findCityById(entertainment.getCityId()).getCityName());
            entertainmentList.add(entertainment);
        }
        return entertainmentList;
    }
    @Override
    public List<Entertainment> findFoodsByKeyWord(String key) {
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(criteriaBuilder.equal(root.get("type"),"food"));
                predicates.add(criteriaBuilder.like(root.get("name"),"%"+ key +"%"));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        return entertainmentRepository.findAll(specification);
    }
    @Override
    public List<Entertainment> findFoodsByKeyWord1(String key, Integer page, Integer size) {
        int pageIndex = (page-1)*size;
        List<Entertainment> entertainments = entertainmentMapper.findFoodsByKeyWord(key,pageIndex,size);
        List<Entertainment> entertainmentList = new ArrayList<>();
        for (Entertainment entertainment:entertainments){
            entertainment.setCityId(cityService.findCityById(entertainment.getCityId()).getCityName());
            entertainmentList.add(entertainment);
        }

        return entertainmentList;
//        Specification specification = new Specification() {
//            @Override
//            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
//                List<Predicate> predicates = new ArrayList<>();
//                predicates.add(criteriaBuilder.equal(root.get("type"),"food"));
//                predicates.add(criteriaBuilder.like(root.get("name"),"%"+ key +"%"));
//                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
//            }
//        };
//
////        List<Entertainment> entertainments =entertainmentRepository.findAll(specification);
////        List<Entertainment> entertainmentList = new ArrayList<>();
////        for (Entertainment entertainment:entertainments){
////            entertainment.setCityId(cityService.findCityById(entertainment.getCityId()).getCityName());
////            entertainmentList.add(entertainment);
////        }
//        return entertainmentRepository.findAll(specification,pageable);
    }

    @Override
    public void deleteById(String entertainmentId) {
        entertainmentRepository.deleteById(entertainmentId);
    }

    @Override
    public Entertainment updateEntertainment(Entertainment entertainment) {
        Entertainment update = entertainmentRepository.saveAndFlush(entertainment);
        return update;
    }


}
